/*
 * @Description: 接口要加上文件目录/admin/articles/xxx
 * @Author: cy
 * @Date: 2024/12/3
 */

var express = require("express");
var router = express.Router();
const { Op } = require("sequelize");

const { Article } = require("../../models");
const { NotFoundError } = require("../../utils/errors");
const { success, failure } = require("../../utils/responses");
const {
  setKey,
  getKey,
  getKeysByPattern,
  delKey,
} = require("../../utils/redis");

/**
 * 清除redis缓存
 * @returns {Promise<void>}
 */
async function clearCache() {
  // 清除所有文章列表缓存
  const keys = await getKeysByPattern("articles:*");
  console.log(keys);

  if (keys.length !== 0) {
    await delKey(keys);
  }
}

/**
 * 公共方法：查询当前文章
 */
async function getArticle(id) {
  const article = await Article.findByPk(id);
  if (!article) {
    throw new NotFoundError(`ID: ${id}的文章未找到。`);
  }

  return article;
}

/*
 * $param
 * @return
 * @desc 文章列表，带模糊搜索
 * select * from Articles where title like '%标题 10%'`
 * 分页
 * SELECT * FROM `Articles` LIMIT offset, pageSize;
 * SELECT * FROM `Articles` LIMIT 0, 10;第一页
 * SELECT * FROM `Articles` LIMIT 10, 10;第二页
 * offset = (currentPage - 1) * pageSize
 * */
router.get("/articlesList", async function (req, res, next) {
  try {
    const query = req.query;
    // 当前是第几页，如果不传，那就是第一页
    const currentPage = Math.abs(Number(query.currentPage)) || 1;

    // 每页显示多少条数据，如果不传，那就显示10条
    const pageSize = Math.abs(Number(query.pageSize)) || 10;

    // 计算 offset
    const offset = (currentPage - 1) * pageSize;

    // 定义查询条件
    const condition = {
      order: [["id", "DESC"]],
      limit: pageSize,
      offset: offset,
    };

    // 专门处理title的模糊搜索
    if (query.title) {
      condition.where = {
        title: {
          [Op.like]: `%${query.title}%`,
        },
      };
    }

    // 处理其他where条件，通用查询条件
    if (
      Object.entries(query)?.filter(
        (e) => !["currentPage", "pageSize", "title"]?.includes(e?.[0])
      )?.length > 0
    ) {
      let obj = condition.where || {};
      Object.entries(query)
        ?.filter((e) => !["currentPage", "pageSize", "title"]?.includes(e?.[0]))
        ?.map((item) => {
          let key = item[0];
          let value = item[1];
          obj[key] = {
            [Op.like]: `%${value}%`,
          };
        });
      condition.where = obj;
    }

    // 定义带有「当前页码」和「每页条数」的 cacheKey 作为缓存的键
    // 如果有title搜索，将title也加入缓存键中
    const titleParam = query.title ? `:${query.title}` : "";
    const cacheKey = `articles:${currentPage}:${pageSize}${titleParam}`;
    let data = await getKey(cacheKey);
    if (data) {
      return success(res, "查询文章列表成功", data);
    }

    // const data = await Article.findAll(condition);
    const { count, rows } = await Article.findAndCountAll(condition);

    data = {
      status: true,
      message: "查询文章列表成功。",
      data: {
        articles: rows,
        pagination: {
          total: count,
          currentPage,
          pageSize,
        },
      },
      query,
    };
    await setKey(cacheKey, data);

    success(res, "查询文章列表成功", data);
  } catch (error) {
    failure(res, error);
  }

  // res.json({
  //   status: true,
  //   message: "查询文章列表成功。",
  //   data: {
  //     articles: rows,
  //     pagination: {
  //       total: count,
  //       currentPage,
  //       pageSize,
  //     },
  //   },
  //   query,
  // });
});
/* 根据ID获取文章详情 */

/**
 * @swagger
 *
 * /articles/{articleId}:
 *   get:
 *     description: 查询单条记录
 *     security:
 *       - ApiKeyAuth: []
 *     tags:
 *       - 文章
 *     parameters:
 *       - name: articleId
 *         in: path
 *         required: true
 *         description: 文章的id
 *         default: 1
 *         schema:
 *           type: integer
 *           format: int64
 *           minimum: 1
 *     responses:
 *       '200':
 *         description: 返回的当前文章
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 id:
 *                   type: integer
 *                   example: 1
 *                 title:
 *                   type: string
 *                   example: 明天可能下雨
 *                 content:
 *                   type: string
 *                   example: 哈哈哈哈
 *               required:
 *                 - id
 *                 - name
 *       '404':
 *         description: 页面未找到
 *
 */
router.get("/:id", async function (req, res, next) {
  const article = await models.Article.findByPk(req.params.id);
  console.log(article);

  res.json({
    ...article,
    currentUser: req.user,
  });
});

router.get("/", async function (req, res, next) {
  try {
    const article = await getArticle(req.query.id);
    // 查询文章详情
    success(res, "查询文章成功。", { article, currentUser: req.user });
  } catch (e) {
    // 如果没有找到，就抛出异常
    failure(res, e);
  }
});

/* 新增或者修改文章 */
router.post("/addOrUpdateArticle", async function (req, res, next) {
  try {
    //根据ID区分创建还是更新
    if (req.body.id) {
      const article = await getArticle(req.body.id);

      // 使用 req.body 获取到用户通过 POST 提交的数据，然后创建文章
      await article.update(req.body, {
        where: { id: req.body.id },
      });
      await clearCache();

      success(res, "更新成功。", { article }, 200);
    } else {
      const article = await Article.create(req.body);
      await clearCache();

      success(res, "创建成功。", { article }, 201);
    }
  } catch (error) {
    failure(res, error);
  }
});

/* 删除文章 */
router.delete("/deleteArticleById", async function (req, res, next) {
  try {
    // 使用 req.body 获取到用户通过 POST 提交的数据，然后删除文章
    /*
     * $param
     * @return
     * @desc 或者先查询文章后，再删除，比如你想提示文字不存在，未找到，如下
     * const article = await Article.findByPk(id);
     * await article.destroy();
     * */
    const article = await Article.destroy({ where: { id: req.body.id } });

    res.status(200).json({
      status: true,
      message: "操作成功。",
      data: article,
    });
  } catch (error) {
    res.status(500).json({
      status: false,
      message: "操作失败。",
      errors: [error.message],
    });
  }
});

module.exports = router;
